package cn.zt.middleware.dynamic.thread.pool.sdk.domain;

import cn.zt.middleware.dynamic.thread.pool.sdk.domain.model.entity.ThreadPoolConfigEntity;
import com.alibaba.fastjson2.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author: zhangtao
 * @description: 动态线程池服务实现类
 * @date: 2024-08-09 11:52
 */

public class DynamicThreadPoolService implements IDynamicThreadPoolService{

    private final Logger logger = LoggerFactory.getLogger(DynamicThreadPoolService.class);

    /**
     * 应用名称
     */
    private final String applicationName;

    /**
     * 线程池执行器映射集合
     */
    private final Map<String, ThreadPoolExecutor> threadPoolExecutorMap;

    public DynamicThreadPoolService(String applicationName, Map<String, ThreadPoolExecutor> threadPoolExecutorMap) {
        this.applicationName = applicationName;
        this.threadPoolExecutorMap = threadPoolExecutorMap;
    }

    /**
     * 查询所有线程池配置
     * @return
     */
    @Override
    public List<ThreadPoolConfigEntity> queryThreadPoolConfigs() {
        Set<String> threadPoolNames = threadPoolExecutorMap.keySet();
        List<ThreadPoolConfigEntity> threadPollVOList = new ArrayList<>(threadPoolNames.size());
        for (String threadPoolName : threadPoolNames) {
            ThreadPoolExecutor executor = threadPoolExecutorMap.get(threadPoolName);
            ThreadPoolConfigEntity threadPoolConfigEntity = new ThreadPoolConfigEntity(applicationName, threadPoolName);
            threadPoolConfigEntity.setActiveCount(executor.getActiveCount());
            threadPoolConfigEntity.setCorePoolSize(executor.getCorePoolSize());
            threadPoolConfigEntity.setMaximumPoolSize(executor.getMaximumPoolSize());
            threadPoolConfigEntity.setPoolSize(executor.getPoolSize());
            threadPoolConfigEntity.setQueueSize(executor.getQueue().size());
            threadPoolConfigEntity.setQueueType(executor.getQueue().getClass().getSimpleName());
            threadPoolConfigEntity.setRemainingCapacity(executor.getQueue().remainingCapacity());
            threadPollVOList.add(threadPoolConfigEntity);
        }
        return threadPollVOList;
    }

    /**
     * 根据线程池名称查询线程池配置
     * @param threadPoolName 线程池名称
     * @return
     */
    @Override
    public ThreadPoolConfigEntity queryThreadPoolConfigByName(String threadPoolName) {
        ThreadPoolExecutor executor =  threadPoolExecutorMap.get(threadPoolName);

        if (null == executor) {
            return new ThreadPoolConfigEntity(applicationName, threadPoolName);
        }

        // 读取线程池配置
        ThreadPoolConfigEntity threadPoolConfigVO = new ThreadPoolConfigEntity(applicationName, threadPoolName);
        threadPoolConfigVO.setCorePoolSize(executor.getCorePoolSize());
        threadPoolConfigVO.setActiveCount(executor.getActiveCount());
        threadPoolConfigVO.setMaximumPoolSize(executor.getMaximumPoolSize());
        threadPoolConfigVO.setPoolSize(executor.getPoolSize());
        threadPoolConfigVO.setQueueSize(executor.getQueue().size());
        threadPoolConfigVO.setQueueType(executor.getQueue().getClass().getSimpleName());
        threadPoolConfigVO.setRemainingCapacity(executor.getQueue().remainingCapacity());

        if (logger.isDebugEnabled()) {
            logger.info("动态线程池，配置查询 应用名:{} 线程名:{} 池化配置:{}", applicationName, threadPoolName, JSON.toJSONString(threadPoolConfigVO));
        }
        return threadPoolConfigVO;
    }

    /**
     * 更新线程池配置
     * @param threadPoolConfigEntity
     */
    @Override
    public void updateThreadPoolConfig(ThreadPoolConfigEntity threadPoolConfigEntity) {
        if (null == threadPoolConfigEntity || null == threadPoolConfigEntity.getThreadPoolName()) {
            return;
        }
        ThreadPoolExecutor executor = threadPoolExecutorMap.get(threadPoolConfigEntity.getThreadPoolName());
        if (null == executor) {
            return;
        }
        // 调整参数 【核心线程+最大线程数】
        // 设置参数 「调整核心线程数和最大线程数」
        // 注意点：
        // 核心线程数<= 最大线程数
        if (threadPoolConfigEntity.getCorePoolSize() > threadPoolConfigEntity.getMaximumPoolSize()) {
            logger.error("动态线程池，配置更新 失败 应用名:{} 线程名:{} 原因：核心线程数 > 最大线程数",
                    applicationName, threadPoolConfigEntity.getThreadPoolName());
        }
        executor.setCorePoolSize(threadPoolConfigEntity.getCorePoolSize());
        executor.setMaximumPoolSize(threadPoolConfigEntity.getMaximumPoolSize());
    }
}
